package com.yunmaozj.tools.site;

import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import okhttp3.*;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

import static java.util.Objects.isNull;

/**
 * @author zhongminghong
 * @email yunmaozj@163.com
 * @create 2019-09-10 11:30
 */
@Mojo(name = "upload", defaultPhase = LifecyclePhase.SITE_DEPLOY, threadSafe = true)
public class DocumentUploadMojo extends AbstractMojo {


    @Parameter(property = "serverId", required = true)
    private String serverId;
    @Parameter(property = "siteURL", required = true)
    private String siteURL;
    @Parameter(property = "projectName")
    private String projectId;
    @Parameter(property = "siteDictDirectory", required = true)
    private File siteDirectory;
    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    private MavenProject project;
    @Component
    private Settings settings;

    @Override
    @SneakyThrows
    public void execute() {
        Server server = settings.getServer(serverId);
        if (isNull(server)) {
            throw new MojoExecutionException("Not Found Server");
        }
        if (isNull(projectId)) {
            projectId = project.getArtifactId();
        }
        if (!siteDirectory.exists()) {
            throw new MojoExecutionException(siteDirectory.getAbsolutePath() + "Is Not Found");
        }
        if (!siteDirectory.isDirectory()) {
            throw new MojoExecutionException(siteDirectory.getAbsolutePath() + "Is Not Directory");
        }
        OkHttpClient client = new OkHttpClient.Builder()
                .build();
        HttpUrl url = HttpUrl.parse(siteURL)
                .newBuilder()
                .build();
        String sessionId = login(server, url, client);
        uploadDeveloper(client, url, projectId, sessionId);
        url = url.newBuilder()
                .addPathSegment("site")
                .addPathSegment("uploadFile")
                .addPathSegment(projectId).build();
        uploadFile(client, url, "", siteDirectory, sessionId);
    }

    /**
     * 上传开发人员信息
     */
    private void uploadDeveloper(OkHttpClient client, HttpUrl url, String projectId, String sessionId) throws IOException, MojoFailureException {
        if (project.getDevelopers().isEmpty()) {
            getLog().info("Not Found developer");
            return;
        }
        url = url.newBuilder()
                .addPathSegment("site")
                .addPathSegment("uploadMetadata")
                .addPathSegment(projectId)
                .build();
        RequestBody body = RequestBody.create(JSONObject.toJSONString(project.getDevelopers()).getBytes(StandardCharsets.UTF_8), MediaType.parse("application/json;charset=utf-8"));
        Request request = new Request.Builder()
                .url(url)
                .header("Cookie", sessionId)
                .post(body)
                .build();
        Response response = client.newCall(request).execute();
        if (response.code() != 200) {
            throw new MojoFailureException("Project Metadata Upload Fail");
        }
        getLog().info("Project Metadata Upload Success");

    }

    private void uploadFile(OkHttpClient client, HttpUrl url, String path, File uploadDirectory, String sessionId) throws IOException, MojoFailureException {

        for (String fileName : uploadDirectory.list()) {
            File file = new File(uploadDirectory, fileName);
            if (file.isDirectory()) {
                uploadFile(client, url, path + "/" + fileName, file, sessionId);
            } else {
                MediaType mediaType = MediaType.parse("image/png");
                RequestBody fileBody = RequestBody.create(mediaType, file);
                RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
                        .addFormDataPart("path", path)
                        .addFormDataPart("file", file.getName(), fileBody)
                        .build();
                Request request = new Request.Builder()
                        .header("Cookie", sessionId)
                        .url(url).post(requestBody).build();
                Response response = client.newCall(request).execute();
                if (response.code() != 200) {
                    throw new MojoFailureException("Project File Upload Fail");
                }
                getLog().info("Project File(" + file.getPath() + ") Upload Success");
            }
        }
    }

    private String login(Server server, HttpUrl url, OkHttpClient client) throws IOException, MojoFailureException {
        Request request = new Request.Builder()
                .url(url.newBuilder()
                        .addPathSegment("site")
                        .addPathSegment("login").build())
                .post(new FormBody.Builder()
                        .add("username", server.getUsername())
                        .add("password", server.getPassword()).build())
                .build();
        Response response = client.newCall(request).execute();
        if (response.code() != 200) {
            throw new MojoFailureException("Login Fail By " + server.getId());
        }
        String cookie = response.header("Set-Cookie");
        if (isNull(cookie)) {
            throw new NullPointerException("The Cookie Is Null");
        }
        String[] JSESSIONID = cookie.split(";");
        return JSESSIONID[0];
    }

}
